/*
 * @(#)MetadataValidator.java
 * Date 2013-10-05
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.registry.model;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.enterprise.context.ApplicationScoped;

import oasis.names.tc.ebxml_regrep.xsd.rim._3.ClassificationType;

import org.apache.commons.lang3.StringUtils;

import org.joda.time.DateTime;

import us.hornerscorners.lamppost.exception.ServiceActionError;
import us.hornerscorners.lamppost.exception.SeverityType;

import us.hornerscorners.lamppost.model.common.CodedElement;
import us.hornerscorners.lamppost.model.common.InstanceIdentifier;
import us.hornerscorners.lamppost.model.common.TimeInterval;

import us.hornerscorners.lamppost.model.document.Author;

import us.hornerscorners.lamppost.registry.constant.ErrorCode;
import us.hornerscorners.lamppost.registry.constant.Metadata;
import us.hornerscorners.lamppost.registry.constant.SlotName;


/**
 * Class description
 *
 *
 * @version        v1.0, 2013-10-05
 * @author         Jim Horner
 */
@ApplicationScoped
public class MetadataValidator {

    /**
     * Constructs ...
     *
     */
    public MetadataValidator() {
        super();
    }

    /**
     * Method description
     *
     *
     * @param author
     *
     * @return
     */
    public Collection<ServiceActionError> validate(ClassificationType ctype,
            Author author) {

        List<ServiceActionError> errors = new ArrayList<>();

        if (StringUtils.isBlank(author.getPerson())
                && author.getTelecommunications().isEmpty()
                && author.getInstitutions().isEmpty()) {

            String msg =
                String.format(
                    "Classification [%s] Author requires at least one of authorPerson, authorTelecommunication or authorInstitution.",
                    ctype.getId());

            ServiceActionError error =
                new ServiceActionError(ErrorCode.XDSRegistryMetadataError.getCode(), msg,
                                       SeverityType.Error);

            errors.add(error);
        }

        return errors;
    }

    /**
     * Method description
     *
     *
     * @param metadata
     * @param value
     *
     * @return
     */
    public Collection<ServiceActionError> validate(Metadata metadata, DateTime value) {

        List<ServiceActionError> errors = new ArrayList<>();

        if (value == null) {

            String msg = String.format("%s is required.", metadata.name());

            errors.add(
                new ServiceActionError(
                    ErrorCode.XDSRegistryMetadataError.getCode(), msg,
                    SeverityType.Error));
        }

        return errors;
    }

    /**
     * Method description
     *
     *
     * @param metadata
     * @param value
     *
     * @return
     */
    public Collection<ServiceActionError> validate(Metadata metadata,
            InstanceIdentifier value) {

        List<ServiceActionError> errors = new ArrayList<>();

        if (value == null) {

            String msg = String.format("%s is required.", metadata.name());

            errors.add(
                new ServiceActionError(
                    ErrorCode.XDSRegistryMetadataError.getCode(), msg,
                    SeverityType.Error));
        }

        return errors;
    }

    /**
     * Method description
     *
     *
     * @param slotName
     * @param value
     *
     * @return
     */
    public Collection<ServiceActionError> validate(SlotName slotName, DateTime value) {

        List<ServiceActionError> errors = new ArrayList<>();

        if (value == null) {

            String msg = String.format("%s is required.", slotName.getCode());

            errors.add(
                new ServiceActionError(
                    ErrorCode.XDSRegistryMetadataError.getCode(), msg,
                    SeverityType.Error));
        }

        return errors;
    }

    /**
     * Method description
     *
     *
     * @param slotName
     * @param value
     *
     * @return
     */
    public Collection<ServiceActionError> validate(SlotName slotName,
            InstanceIdentifier value) {

        List<ServiceActionError> errors = new ArrayList<>();

        if (value == null) {

            String msg = String.format("%s is required.", slotName.getCode());

            errors.add(
                new ServiceActionError(
                    ErrorCode.XDSRegistryMetadataError.getCode(), msg,
                    SeverityType.Error));
        }

        return errors;
    }

    /**
     * Method description
     *
     *
     * @param slotName
     * @param value
     *
     * @return
     */
    public Collection<ServiceActionError> validate(SlotName slotName, String value) {

        List<ServiceActionError> errors = new ArrayList<>();

        if (StringUtils.isBlank(value)) {

            String msg = String.format("%s is required.", slotName.getCode());

            errors.add(
                new ServiceActionError(
                    ErrorCode.XDSRegistryMetadataError.getCode(), msg,
                    SeverityType.Error));
        }

        return errors;
    }

    /**
     * Method description
     *
     *
     * @param metadata
     * @param code
     * @param displayNameRequired
     *
     * @return
     */
    public Collection<ServiceActionError> validate(Metadata metadata, CodedElement code,
            boolean displayNameRequired) {

        List<CodedElement> codes = new ArrayList<>();

        if (code != null) {
            codes.add(code);
        }

        return validate(metadata, codes, displayNameRequired);
    }

    /**
     * Method description
     *
     *
     * @param displayNameRequired
     *
     * @return
     */
    public Collection<ServiceActionError> validate(Metadata metadata,
            Collection<CodedElement> codes, boolean displayNameRequired) {

        List<ServiceActionError> errors = new ArrayList<>();

        if (codes.isEmpty()) {

            String msg = String.format("%s is required.", metadata.name());

            errors.add(
                new ServiceActionError(
                    ErrorCode.XDSRegistryMetadataError.getCode(), msg,
                    SeverityType.Error));

        } else if ((displayNameRequired == true)) {

            for (CodedElement code : codes) {

                if (code.getDisplayNames().isEmpty()) {

                    String msg = String.format("%s displayNames is required.",
                                               metadata.name());

                    errors.add(
                        new ServiceActionError(
                            ErrorCode.XDSRegistryMetadataError.getCode(), msg,
                            SeverityType.Error));
                }
            }
        }

        return errors;

    }

    /**
     * Method description
     *
     *
     * @param startSlotName
     * @param stopSlotName
     * @param interval
     *
     * @return
     */
    public Collection<ServiceActionError> validate(SlotName startSlotName,
            SlotName stopSlotName, TimeInterval interval) {

        List<ServiceActionError> errors = new ArrayList<>();

        DateTime start = interval.getStart();
        DateTime stop = interval.getStop();

        if ((start != null) && (stop != null)) {

            if (start.isAfter(stop)) {

                String msg = String.format("%s must be before or the same as %s.",
                                           startSlotName.getCode(),
                                           stopSlotName.getCode());

                errors.add(
                    new ServiceActionError(
                        ErrorCode.XDSRegistryMetadataError.getCode(), msg,
                        SeverityType.Error));
            }
        }

        return errors;
    }
}
